﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace BezierApp
{
    /// <summary>
    /// Slow bezier cubica
    /// </summary>
    public class BezierCurve
    {
        public VertexBuffer VertexBuffer;
        public VertexDeclaration VertexDeclaration;
        public int PrimitiveCount;
        public int VertexBufferSize;

        public BezierCurve(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
        {
            this.p0 = p0;
            this.p1 = p1;
            this.p2 = p2;
            this.p3 = p3;
        }

        public void Create(GraphicsDevice GraphicsDevice)
        {
            Create(GraphicsDevice, 0.01f);
        }

        public void Create(GraphicsDevice GraphicsDevice, float step)
        {
            List<VertexPositionColor> vertexList = new List<VertexPositionColor>();

            PrimitiveCount = -1;
            VertexBufferSize = 0;
            for (float i = 0; i < 1; i += step)
            {
                VertexPositionColor v;
                v.Position = Evaluate(i);
                v.Color = Color.White;
                vertexList.Add(v);
                PrimitiveCount++;
                VertexBufferSize++;
            }

            VertexDeclaration = new VertexDeclaration(GraphicsDevice, VertexPositionColor.VertexElements);

            var newVertices = new VertexPositionColor[vertexList.Count];
            vertexList.CopyTo(newVertices);

            VertexBuffer = new VertexBuffer(GraphicsDevice, newVertices.Length * VertexPositionColor.SizeInBytes, BufferUsage.WriteOnly);
            VertexBuffer.SetData(newVertices);

        }

        Vector3 p0;
        Vector3 p1;
        Vector3 p2;
        Vector3 p3;

        public Vector3 Evaluate(float t)
        {
            Vector3 resp;
            resp = p0 * Pow(1 - t, 3) + p1 * 3 * t * Pow(1 - t, 2) + p2 * 3 * t * t * (1 - t) + p3 * t * t * t;
            return resp;
        }

        private float Pow(float v, float elevado)
        {
            return (float)Math.Pow(v, elevado);
        }
    }
}
